package core.lib.model;

import java.net.URI;
import java.util.Enumeration;
import java.util.Hashtable;

import core.lib.CoreConstants;
import core.lib.interfaces.ICRequestCallback;

/**
 * <code>Request</code>是<code>Module</code>之间交互的唯一消息类型。它是一个纯数据类，既是作为请求时候，
 * 负责传送消息参数和相关信息的对象，也是负责请求处理完毕以后，送回结果数据和通知监听器的对象。
 * 
 * @author <a href="mailto:cu2oh2co3@263.net">Ryan</a>
 * @since 1.0
 */
public final class CoreRequest
{
	public static final int PRIORITY_LOW = -1;
	public static final int PRIORITY_NORMAL = 0;
	public static final int PRIORITY_HIGH = 1;
	public static final int PRIORITY_URGENT = 127;

	public static final int STATUS_NEW = 0;
	public static final int STATUS_SUCCEED = 1;
	public static final int STATUS_FAILED = 2;

	protected final URI m_targetURI;

	private int m_responseCode = STATUS_NEW;
	private int m_priority = PRIORITY_NORMAL;
	private int id;	
	private Object m_response;
	private CoreRequest m_linkedRequest;
	private ICRequestCallback mRequestCallBack;
	private Hashtable<String, Object> m_parameters;
	private boolean m_responseFlag = true;

	/**
	 * 构造方法。
	 * 
	 * @param senderClassName
	 *            构造<code>Request</code>的类对象名
	 * @param requestType
	 *            <code>Request</code>的类型
	 * @param actionType
	 *            <code>Request</code>的动作类型
	 */
	public CoreRequest(URI requestType, ICRequestCallback callback)
	{
		m_targetURI = requestType;
		mRequestCallBack = callback;
	}
	
	public int getId()
	{
		return id;
	}

	public void setId(int id)
	{
		this.id = id;
	}

	/**
	 * 往<code>Request</code>中添加一个参数
	 * 
	 * @param key
	 *            参数标识，取自<code>Constants</code>中以PARA开头的字段
	 * @param value
	 *            参数值
	 */
	public final void addParameter(String key, Object value)
	{
		if (key == null)
		{
			throw new IllegalArgumentException("The key can not be null!");
		}

		if (value != null)
		{
			// Lazy load
			if (m_parameters == null)
			{
				m_parameters = new Hashtable<String, Object>();
			}

			m_parameters.put(key, value);
		}
	}

	public final synchronized boolean equals(Object obj)
	{
		if (this == obj)
		{
			return true;
		}

		if (obj instanceof CoreRequest)
		{
			CoreRequest req = (CoreRequest) obj;

			if (m_targetURI == req.m_targetURI)
			{

				if (req.m_parameters.size() == 0 && m_parameters.size() == 0)
				{
					return true;
				}

				if (req.m_parameters.size() != m_parameters.size())
				{
					return false;
				}

				Enumeration<String> e = req.m_parameters.keys();
				while (e.hasMoreElements())
				{
					String key = e.nextElement();
					Object a, b;
					a = req.m_parameters.get(key);
					b = m_parameters.get(key);
					if (a == b || (a == null && b == null))
					{
						continue;
					}
					else
					{
						if (a == null || b == null || !a.equals(b))
						{
							return false;
						}
					}
				}
				return true;
			}
		}
		return false;
	}

	public int hashCode()
	{
		// 没有制定hashCode规则，有需求的时候再考虑
		throw new IllegalArgumentException("Request is not proposed to be put into any hash container.");
	}

	/**
	 * 取得该<code>Request</code>关联的<code>Request</code>
	 * 
	 * @return 该<code>Request</code>关联的<code>Request</code>
	 */
	public final CoreRequest getLinkedRequest()
	{
		return m_linkedRequest;
	}

	/**
	 * 取得一个参数值
	 * 
	 * @param key
	 *            参数标识
	 * @return 参数值。如果没找到该参数，则返回null
	 */
	public final Object getParameter(String key)
	{
		if (m_parameters == null)
		{
			return null;
		}
		else
		{
			return m_parameters.get(key);
		}
	}

	/**
	 * 取得该<code>Request</code>的优先值
	 * 
	 * @return 该<code>Request</code>的优先值
	 */
	public final int getPriority()
	{
		return m_priority;
	}

	/**
	 * 取得该<code>Request</code>的类型常量。
	 * 
	 * @return 该<code>Request</code>的类型常量。常量表见<code>Constants</code>
	 */
	public final URI getURI()
	{
		return m_targetURI;
	}

	/**
	 * 取得一个结果数据。
	 * 
	 * @param key
	 *            结果数据的标识
	 * @return 结果数据
	 */
	public final synchronized Object getResponse()
	{
		return m_response;
	}

	/**
	 * 取得返回结果状态码
	 * 
	 * @return 返回结果状态码
	 */
	public final int getResponseCode()
	{
		return m_responseCode;
	}

	/**
	 * 设置该<code>Request</code>关联的<code>Request</code>
	 * 
	 * @param request
	 *            要关联的<code>Request</code>
	 */
	public final void setLinkedRequest(CoreRequest request)
	{
		m_linkedRequest = request;
	}

	/**
	 * 设置该<code>Request</code>的优先值
	 * 
	 * @param priority
	 *            要设置的优先值
	 */
	public final void setPriority(int priority)
	{
		m_priority = priority;
	}

	/**
	 * 设置该<code>Request</code>的状态，并在状态改变后通知所有的监听者。
	 * 
	 * @param responseCode
	 *            返回状态码
	 * @param reponse
	 *            server返回的数据
	 */
	public final synchronized void setResponse(int responseCode, Object reponse)
	{
		// 只能响应一次
		if (m_responseFlag)
		{
			m_responseFlag = false;
			m_response = reponse;
			m_responseCode = responseCode;
			if (mRequestCallBack != null)
			{
				new Thread()
				{
					public void run()
					{
						try
						{
							CoreRequest.this.mRequestCallBack.onRequestFinshed(CoreRequest.this);
						}
						catch (Exception e)
						{
							CoreRequest.this.mRequestCallBack.onRequestError(CoreRequest.this, CoreConstants.RequestReturnCode.FATAL_ERROR, "");
						}
						catch (Error e)
						{
							CoreRequest.this.mRequestCallBack.onRequestError(CoreRequest.this, CoreConstants.RequestReturnCode.FATAL_ERROR, "");
						}
					}

				}.start();
			}
		}
		else
		{
			CoreRequest.this.mRequestCallBack.onRequestError(CoreRequest.this, CoreConstants.RequestReturnCode.FATAL_ERROR, "A certain request can not be called-back twice!");
		}
	}
}
